package org.dyndns.opendemogroup.optimizer.operations;

import static org.junit.Assert.*;

import java.util.Random;

import org.dyndns.opendemogroup.optimizer.ArrayUtil;
import org.dyndns.opendemogroup.optimizer.Member;
import org.dyndns.opendemogroup.optimizer.Pair;
import org.junit.Test;

/**
 * A class to test the class OrderPreservingOperationBase
 */
public class OrderPreservingOperationBaseTest
{

	private OrderPreservingOperationBase implementation;

	public OrderPreservingOperationBaseTest ( )
	{
	}

	public OrderPreservingOperationBaseTest (
			OrderPreservingOperationBase implementation )
	{
		this.implementation = implementation;
	}

	/**
	 * Tests the <i>pickPoints</i> method with a few boundary checks over a
	 * simulation run.
	 */
	@Test
	public void pickPoints_SimulationBoundaryChecks ( )
	{
		Random randomSource = new Random ( 42 );
		final int memberSize = 20;
		int[] firstDistribution = new int[memberSize];
		int[] secondDistribution = new int[memberSize];
		for ( int i = 0; i < 1000; i++ )
		{
			String message = "Run #" + i;
			Pair<Integer, Integer> actual =
				OrderPreservingOperationBase.pickPoints ( randomSource,
					memberSize );
			// { check that first is before second and there's a gap >= 1
			assertTrue ( message, ( actual.second - actual.first ) >= 1 );
			// }
			// { keep some statistics
			firstDistribution[actual.first]++;
			secondDistribution[actual.second]++;
			// }
		}
	}

	void checkPerform ( double[] one, double[] two, int a, int b,
			double[] expectedChild )
	{
		// { sanity checks
		int length = one.length;
		assertEquals ( length, two.length );
		assertEquals ( length, expectedChild.length );
		// }

		// { set-up
		Member parentOne = new Member ( length );
		ArrayUtil.copy ( one, parentOne.genome, 0, length - 1 );
		Member parentTwo = new Member ( length );
		ArrayUtil.copy ( two, parentTwo.genome, 0, length - 1 );

		Member child = new Member ( length );
		implementation.perform ( parentOne, parentTwo, child, a, b );
		// }

		// { validation
		OperationTestBase.checkChild ( child, expectedChild );
		// }
	}

}
